/*自定義的 調試用的 宏
所有 宏只在 定義了 相應日誌等級 時 才工作
在沒 定義 時 被替換為 空



日誌等級
KING_DEBUG_TRACE
KING_DEBUG_DEBUG
KING_DEBUG_INFO
KING_DEBUG_FAULT
KING_DEBUG_ERROR

如果定義了 KING_DEBUG_USE_RELEASE 則 KING_DEBUG_INFO KING_DEBUG_FAULT KING_DEBUG_ERROR 被自動定義
如果定義了 KING_DEBUG_USE_DEBUG   則 所有日誌等級 被自動定義



向 debug 流 輸出 相應等級 日誌
KING_TRACE(XXX)
KING_DEBUG(XXX)
KING_INFO(XXX)
KING_FAULT(XXX)
KING_ERROR(XXX)
KING_FORMAT_TRACE(XXX)
KING_FORMAT_DEBUG(XXX)
KING_FORMAT_INFO(XXX)
KING_FORMAT_FAULT(XXX)
KING_FORMAT_ERROR(XXX)

//輸出時 加鎖操作 默認為空
KING_DEBUG_LOCK
KING_DEBUG_UNLOCK


在include前 定義 KING_DEBUG_TAG_XXX (如 KING_DEBUG_TAG_TRACE) 可以 修改 tag

KING_DEBUG_SHOW_FILE   非0 顯示 代碼 文件 默認為0
KING_DEBUG_SHOW_LINE   非0 顯示 代碼 行數 默認為0
KING_DEBUG_SHOW_TAG    非0 顯示 日誌 等級 默認為1
KING_DEBUG_COUT_FLUSH  非0 每次 寫入日誌後 刷新 默認為0

KING_DEBUG_STREAM   日誌輸出流 默認為 std::cout



//在指定 等級下 定義 一段 代碼
KING_TRACE_SECTION(XXX)
KING_DEBUG_SECTION(XXX)
KING_INFO_SECTION(XXX)
KING_FAULT_SECTION(XXX)
KING_ERROR_SECTION(XXX)

//在指定 定義了 KING_DEBUG_X 時 定義 一段 代碼
KING_DEBUG_X_SECTION(XXX)
*/
#ifndef KING_LIB_HEADER_DEBUG
#define KING_LIB_HEADER_DEBUG

#include <iostream>
#include <cstdio>



#ifdef KING_DEBUG_USE_RELEASE
#define KING_DEBUG_INFO
#define KING_DEBUG_FAULT
#define KING_DEBUG_ERROR
#endif // KING_DEBUG_USE_RELEASE

#ifdef KING_DEBUG_USE_DEBUG
#define KING_DEBUG_TRACE
#define KING_DEBUG_DEBUG
#define KING_DEBUG_INFO
#define KING_DEBUG_FAULT
#define KING_DEBUG_ERROR
#endif // KING_DEBUG_USE_DEBUG




//數據 過濾 等級
#define _KING_DEBUG_LV_TRACE  1
#define _KING_DEBUG_LV_DEBUG  2
#define _KING_DEBUG_LV_INFO   3
#define _KING_DEBUG_LV_FAULT  4
#define _KING_DEBUG_LV_ERROR  5

#ifndef KING_DEBUG_TAG_TRACE
#define KING_DEBUG_TAG_TRACE "[trace]"
#endif // KING_DEBUG_TAG_TRACE

#ifndef KING_DEBUG_TAG_DEBUG
#define KING_DEBUG_TAG_DEBUG "[debug]"
#endif // KING_DEBUG_TAG_DEBUG

#ifndef KING_DEBUG_TAG_INFO
#define KING_DEBUG_TAG_INFO "[info]"
#endif // KING_DEBUG_TAG_INFO

#ifndef KING_DEBUG_TAG_FAULT
#define KING_DEBUG_TAG_FAULT "[fault]"
#endif // KING_DEBUG_TAG_FAULT

#ifndef KING_DEBUG_TAG_ERROR
#define KING_DEBUG_TAG_ERROR "[error]"
#endif // KING_DEBUG_TAG_ERROR



//定義 顯示 信息
#ifndef KING_DEBUG_SHOW_FILE    //非0 顯示 代碼 文件
#define KING_DEBUG_SHOW_FILE 0
#endif // KING_DEBUG_SHOW_FILE

#ifndef KING_DEBUG_SHOW_LINE    //非0 顯示 代碼 行數
#define KING_DEBUG_SHOW_LINE 0
#endif // KING_DEBUG_SHOW_LINE

#ifndef KING_DEBUG_SHOW_TAG     //非0 顯示 日誌 等級
#define KING_DEBUG_SHOW_TAG 1
#endif // KING_DEBUG_SHOW_TAG

#ifndef KING_DEBUG_COUT_FLUSH   //非0 每次 寫入日誌後 刷新
#define KING_DEBUG_COUT_FLUSH 0
#endif // KING_DEBUG_COUT_FLUSH


//定義lock
#ifndef KING_DEBUG_LOCK
#define KING_DEBUG_LOCK
#endif // KING_DEBUG_LOCK

#ifndef KING_DEBUG_UNLOCK
#define KING_DEBUG_UNLOCK
#endif // KING_DEBUG_UNLOCK


//輸出位置
#ifndef KING_DEBUG_STREAM
#define KING_DEBUG_STREAM   std::cout
#endif // KING_DEBUG_STREAM

//顯示 數據
#define _KING_DEBUG_COUT(TAG,XXX) {\
    KING_DEBUG_LOCK\
    if(KING_DEBUG_SHOW_FILE)KING_DEBUG_STREAM<<__FILE__<<" ";\
    if(KING_DEBUG_SHOW_LINE)KING_DEBUG_STREAM<<"line:"<<__LINE__<<" ";\
    if(KING_DEBUG_SHOW_TAG)KING_DEBUG_STREAM<<TAG<<"\t";\
    if(KING_DEBUG_COUT_FLUSH)\
        KING_DEBUG_STREAM<<XXX<<std::endl;\
    else\
        KING_DEBUG_STREAM<<XXX<<"\n";\
    KING_DEBUG_UNLOCK \
}

#define _KING_DEBUG_ROUTER_COUT(TAG,LV,XXX) switch(LV){\
    case _KING_DEBUG_LV_TRACE:_KING_DEBUG_COUT(TAG,XXX);break;\
    case _KING_DEBUG_LV_DEBUG:_KING_DEBUG_COUT(TAG,XXX);break;\
    case _KING_DEBUG_LV_INFO:_KING_DEBUG_COUT(TAG,XXX);break;\
    case _KING_DEBUG_LV_FAULT:_KING_DEBUG_COUT(TAG,XXX);break;\
    case _KING_DEBUG_LV_ERROR:_KING_DEBUG_COUT(TAG,XXX);break;\
}

//printf 輸出
#ifndef KING_DEBUG_FORMAT_BUFFER
#define KING_DEBUG_FORMAT_BUFFER 1024
#endif // KING_DEBUG_FORMAT_BUFFER


#define _KING_DEBUG_FORMAT_COUT(TAG,...) {\
    char buf[KING_DEBUG_FORMAT_BUFFER];\
    sprintf(buf,__VA_ARGS__ );\
    _KING_DEBUG_COUT(TAG,buf);\
}
#define _KING_DEBUG_FORMAT_ROUTER_COUT(TAG,LV,...) switch(LV){\
    case _KING_DEBUG_LV_TRACE:_KING_DEBUG_FORMAT_COUT(TAG,__VA_ARGS__);break;\
    case _KING_DEBUG_LV_DEBUG:_KING_DEBUG_FORMAT_COUT(TAG,__VA_ARGS__);break;\
    case _KING_DEBUG_LV_INFO:_KING_DEBUG_FORMAT_COUT(TAG,__VA_ARGS__);break;\
    case _KING_DEBUG_LV_FAULT:_KING_DEBUG_FORMAT_COUT(TAG,__VA_ARGS__);break;\
    case _KING_DEBUG_LV_ERROR:_KING_DEBUG_FORMAT_COUT(TAG,__VA_ARGS__);break;\
}




//在定義了 KING_DEBUG_TRACE 時工作
#ifdef KING_DEBUG_TRACE
#define KING_TRACE(XXX) _KING_DEBUG_ROUTER_COUT(KING_DEBUG_TAG_TRACE,_KING_DEBUG_LV_TRACE,XXX)
#define KING_FORMAT_TRACE(...) _KING_DEBUG_FORMAT_ROUTER_COUT(KING_DEBUG_TAG_TRACE,_KING_DEBUG_LV_TRACE,__VA_ARGS__)
#else
#define KING_TRACE(XXX)
#define KING_FORMAT_TRACE(...)
#endif // KING_DEBUG_TRACE

//在定義了 KING_DEBUG_DEBUG 時工作
#ifdef KING_DEBUG_DEBUG
#define KING_DEBUG(XXX) _KING_DEBUG_ROUTER_COUT(KING_DEBUG_TAG_DEBUG,_KING_DEBUG_LV_DEBUG,XXX)
#define KING_FORMAT_DEBUG(...) _KING_DEBUG_FORMAT_ROUTER_COUT(KING_DEBUG_TAG_DEBUG,_KING_DEBUG_LV_DEBUG,__VA_ARGS__)
#else
#define KING_DEBUG(XXX)
#define KING_FORMAT_DEBUG(...)
#endif // KING_DEBUG_DEBUG

//在定義了 KING_DEBUG_INFO 時工作
#ifdef KING_DEBUG_INFO
#define KING_INFO(XXX) _KING_DEBUG_ROUTER_COUT(KING_DEBUG_TAG_INFO,_KING_DEBUG_LV_INFO,XXX)
#define KING_FORMAT_INFO(...) _KING_DEBUG_FORMAT_ROUTER_COUT(KING_DEBUG_TAG_INFO,_KING_DEBUG_LV_INFO,__VA_ARGS__)
#else
#define KING_INFO(XXX)
#define KING_FORMAT_INFO(...)
#endif // KING_DEBUG_INFO

//在定義了 KING_DEBUG_FAULT 時工作
#ifdef KING_DEBUG_FAULT
#define KING_FAULT(XXX) _KING_DEBUG_ROUTER_COUT(KING_DEBUG_TAG_FAULT,_KING_DEBUG_LV_FAULT,XXX)
#define KING_FORMAT_FAULT(...) _KING_DEBUG_FORMAT_ROUTER_COUT(KING_DEBUG_TAG_FAULT,_KING_DEBUG_LV_FAULT,__VA_ARGS__)
#else
#define KING_FAULT(XXX)
#define KING_FORMAT_FAULT(...)
#endif // KING_DEBUG_FAULT

//在定義了 KING_DEBUG_ERROR 時工作
#ifdef KING_DEBUG_ERROR
#define KING_ERROR(XXX) _KING_DEBUG_ROUTER_COUT(KING_DEBUG_TAG_ERROR,_KING_DEBUG_LV_ERROR,XXX)
#define KING_FORMAT_ERROR(...) _KING_DEBUG_FORMAT_ROUTER_COUT(KING_DEBUG_TAG_ERROR,_KING_DEBUG_LV_ERROR,__VA_ARGS__)
#else
#define KING_ERROR(XXX)
#define KING_FORMAT_ERROR(...)
#endif // KING_DEBUG_ERROR





/*
#ifdef KING_DEBUG_XXX
...
#endif
的 簡寫模式
*/
#ifdef KING_DEBUG_TRACE
#define KING_TRACE_SECTION(XXX) XXX
#else
#define KING_TRACE_SECTION(XXX)
#endif // KING_DEBUG_TRACE

#ifdef KING_DEBUG_DEBUG
#define KING_DEBUG_SECTION(XXX) XXX
#else
#define KING_DEBUG_SECTION(XXX)
#endif // KING_DEBUG_DEBUG

#ifdef KING_DEBUG_INFO
#define KING_INFO_SECTION(XXX) XXX
#else
#define KING_INFO_SECTION(XXX)
#endif // KING_DEBUG_INFO

#ifdef KING_DEBUG_FAULT
#define KING_FAULT_SECTION(XXX) XXX
#else
#define KING_FAULT_SECTION(XXX)
#endif // KING_DEBUG_FAULT

#ifdef KING_DEBUG_ERROR
#define KING_ERROR_SECTION(XXX) XXX
#else
#define KING_ERROR_SECTION(XXX)
#endif // KING_DEBUG_ERROR



#ifdef KING_DEBUG_X
#define KING_DEBUG_X_SECTION(XXX) XXX
#else
#define KING_DEBUG_X_SECTION(XXX)
#endif // KING_DEBUG_X


#endif // KING_LIB_HEADER_DEBUG
